﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AMS.Chess.CommonLayer
{
    public abstract class AChessPiece
    {
        protected ChessColor _color;
        public ChessColor Color { get { return _color; } }

        protected AChessBoard _board;
        public AChessBoard ChessBoard { get { return _board; } }

        protected ABoardPosition _position;
        protected AMove _move;

        public AChessPiece(AChessBoard board, ChessColor color)
        {
            _board = board;
            _color = color;
            _move = CreateMove();
        }

        public void SetMove(AMove move)
        {
            _move = move;
        }

        /// <summary>
        /// This method should only be used by the ChessBoard after the Chessboard has set
        /// the piece's position in its tracker.
        /// </summary>
        /// <param name="position"></param>
        public void SetPosition(ABoardPosition position)
        {
            // check to make sure that the board has this piece set
            AChessPiece piece = _board.GetPiece(position);
            if (piece != this)
                throw new InvalidOperationException("Piece/Board position mismatch");

            _position = position;
        }

        public List<ABoardPosition> GetPossibleMoves()
        {
            if (_move == null)  // a piece with no AMove has zero valid spaces
                return new List<ABoardPosition>();

            // opens floor for PieceDecorator that decorates this method by modifying
            // this output

            return _move.GetPossibleMoves(this, _position);
        }

        public void MoveTo(ABoardPosition targetPosition)
        {
            // is this a valid position on the board?
            if (!_board.IsValidPosition(targetPosition))
                throw new InvalidOperationException("Specified position is invalid for this board");

            // is this a valid move target for this piece?
            if (!IsValidMoveTarget(targetPosition))
            {
                throw new InvalidOperationException("Attempted move is not a valid move for specified piece");
            }

            // tell board to change piece's position, then changes its own position
            _board.ChangePiecePosition(this, _position, targetPosition);
            //_position = targetPosition;   // board handles this so that moving can be called here or by board
        }

        // implement in an intermediate abstract class (ie., AStandardChessPiece)
        public abstract bool IsValidMoveTarget(ABoardPosition targetPosition);

        public abstract AMove CreateMove();

        private ABoardPosition oldPosition;
        public void Captured()
        {
            oldPosition = _position;
            _position = null;
        }

        public void UndoCaptured()
        {
            _position = oldPosition;
            oldPosition = null;
        }
    }
}
